package com.lai.qq.route.gateway.service;

/**
 * @author: ou.xiangrui
 * @date : 2020/4/22
 */

import java.util.ArrayList;
import java.util.List;

import com.lai.qq.route.gateway.entity.GateWayEntity;
import com.lai.qq.route.gateway.mapper.GateWayEntityMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;

import reactor.core.publisher.Mono;

/**
 * 数据库方式保存和刷新路由方式
 * 
 * @author ou.xiangrui
 */
@Service
public class GatewayService implements ApplicationEventPublisherAware {
    private ApplicationEventPublisher publisher;
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    @Autowired
    private GateWayEntityMapper gateWayEntityMapper;

    private static final List<String> ROUTE_LIST = new ArrayList<>();

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    public String loadRoute() {
        List<GateWayEntity> gateWayEntities = gateWayEntityMapper.selectAll();

        for (GateWayEntity gateWayEntity : gateWayEntities) {
            RouteDefinition routeDefinition =
                JSONObject.parseObject(gateWayEntity.getRouteRule(), RouteDefinition.class);
            add(routeDefinition);
        }
        return "success";
    }

    private void clearRoute() {
        for (String id : ROUTE_LIST) {
            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
        }
        ROUTE_LIST.clear();
    }

    /**
     * 发布事件
     */
    private void publish() {
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    /**
     *
     * 增加路由
     *
     * @param definition
     *
     * @return
     *
     */
    public String add(RouteDefinition definition) {
        try {
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            ROUTE_LIST.add(definition.getId());
            publish();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "success";
    }

    public String addRoute(String routeId) {
        GateWayEntity entity = new GateWayEntity();
        entity.setRouteId(routeId);
        GateWayEntity gateWayEntity = gateWayEntityMapper.selectOne(entity);
        RouteDefinition routeDefinition = JSONObject.parseObject(gateWayEntity.getRouteRule(), RouteDefinition.class);
        // 保持两个数据库字段和json中routeid一致
        if (!gateWayEntity.getRouteId().equals(routeDefinition.getId())) {
            gateWayEntity.setRouteId(routeDefinition.getId());
            gateWayEntityMapper.updateByPrimaryKey(gateWayEntity);
        }
        return add(routeDefinition);
    }

    /**
     *
     * 更新路由
     *
     * @param definition
     *
     * @return
     *
     */
    public String update(RouteDefinition definition) {
        try {
            this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
            ROUTE_LIST.remove(definition.getId());
        } catch (Exception e) {
            return "update fail,not find route  routeId: " + definition.getId();
        }
        try {
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            ROUTE_LIST.add(definition.getId());
            publish();
            return "success";
        } catch (Exception e) {
            return "update route  fail";
        }
    }

    public String upateRoute(String routeId) {
        GateWayEntity entity = new GateWayEntity();
        entity.setRouteId(routeId);
        GateWayEntity gateWayEntity = gateWayEntityMapper.selectOne(entity);
        if (null == gateWayEntity) {
            return null;
        }
        RouteDefinition routeDefinition = JSONObject.parseObject(gateWayEntity.getRouteRule(), RouteDefinition.class);

        // 保持两个数据库字段和json中routeid一致
        if (!gateWayEntity.getRouteId().equals(routeDefinition.getId())) {
            gateWayEntity.setRouteId(routeDefinition.getId());
            gateWayEntityMapper.updateByPrimaryKey(gateWayEntity);
        }
        return update(routeDefinition);
    }

    /**
     *
     * 删除路由
     *
     * @param id
     *
     * @return
     *
     */
    public String delete(String id) {
        try {
            this.routeDefinitionWriter.delete(Mono.just(id));
            ROUTE_LIST.remove(id);
            return "delete success";
        } catch (Exception e) {
            e.printStackTrace();
            return "delete fail";
        }
    }

    public String deleteRoute(String routeId) {
        GateWayEntity entity = new GateWayEntity();
        entity.setRouteId(routeId);
        gateWayEntityMapper.delete(entity);
        return delete(routeId);
    }

}